package team3;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/** An AI interface that allows a human to play the Game.
 * <p>
 * Works by blocking in <code>makeMove</code> until the user interface provides a
 * valid move to make through <code>move(move)</code>.
 * <p>
 * This relies on the fact that the GameManager and the User Interface are run
 * on different threads.
 * <p>
 * This class partially relies on the fact that the human is expected to retry
 * its move if timing is off: for example, trying to make a move before it is
 * the humans turn. If move is called while makeMove is not or is not yet
 * blocking, then there should be no effect once makeMove does begin blocking.
 */
public class Human extends project2.AI
{
	private Condition moveMade;
	private ReentrantLock lock;
	private int[] moveToMake;

    /** Builds a Human, fresh from the electron mills.
     * @param player The player color the Human will use.
     */
	public Human(AI.Player player)
	{
		super(player, Difficulty.EASY);
		lock = new ReentrantLock();
		moveMade = lock.newCondition();
	}

    /** Blocks until <code>move(move)</code> is called with a valid move.
     * <p>
     * Uses a lock and condition variable to block until <code>move(move)</code>
     * is called on a different thread with a valid move. Will immediately return
     * with an invalid move if no valid moves are available.
     * @param boardState The current game state.
     * @param lastMove The move made by the previous player
     * @return The move selected by a Human, or BoardState.INVALID_MOVE if no move is available
     * @see project2.AI#makeMove(project2.AI.Player[][], int[])
     */
	public int[] makeMove(Player[][] boardState, int[] lastMove)
	{
		BoardState board = new BoardState(boardState);
        //if no valid moves, immediately return
		if(board.getAvailableMoves(getPlayer()).size()==0)
			return new int[]{-1,-1};
		while(true)
		{
			lock.lock();
			try
			{
                //wait for a signal that move has been selected
				moveMade.awaitUninterruptibly();
                //if valid, return it
				if(board.moveIsValid(getPlayer(), moveToMake))
					return moveToMake;
			}
			finally
			{
				lock.unlock();
			}
		}
	}

    /**Tells the AI to attempt making move <code>move</code>.
     * @param move The move selected by the UI
     */
	public void move(int[] move)
	{
		lock.lock();
		try
		{
			moveToMake=move;
            //tell makeMove that a move has been made.
			moveMade.signal();
		}
		finally
		{
			lock.unlock();
		}
	}
}
